import * as THREE from 'three';
import { useThrottleFn } from '@vueuse/core';
import { loadGltf } from '../three-utils';

type UseLodParams = {
  modelList: string[];
  getScene: () => THREE.Scene;
  getCamera: () => THREE.Camera;
  onLoad: (mesh: THREE.Group<THREE.Object3DEventMap>, modelName: string) => void;
};

enum Level {
  High = 'high',
  Medium = 'medium',
  Low = 'low',
}

export default function useLodLoadModel(data: UseLodParams) {
  const lodObjects: { [key: string]: THREE.LOD } = {};
  const modelSet = new Set(data.modelList);
  const loadedModelLevels = new Map<string, Set<number>>(); // 使用 Map 存储已加载的模型级别
  const camera = data.getCamera();
  const scene = data.getScene();

  const level2Text = {
    0: Level.High,
    1: Level.Medium,
    2: Level.Low,
  };

  const loadModels = () => {
    modelSet.forEach((modelName) => {
      lodObjects[modelName] = new THREE.LOD();
      scene.add(lodObjects[modelName]);
      loadedModelLevels.set(modelName, new Set());
    });
  };

  const loadModelLazy = (modelName: string, level: number) => {
    const modelPath = `/model/${modelName}/${level2Text[level]}/model.gltf`;
    loadGltf({
      modelPath,
    }).then((gltf) => {
      const mesh = gltf.scene;
      typeof data.onLoad === 'function' && data.onLoad(mesh, modelName);
      mesh.updateMatrixWorld();
      mesh.matrixAutoUpdate = false;
      lodObjects[modelName].addLevel(mesh, level * 2.5);
    });
  };

  const onLodAnimate = () => {
    for (const [modelName, lod] of Object.entries(lodObjects)) {
      let currentLevel = 2;
      const distance = camera.position.distanceTo(lod.position);
      if (distance <= 4 && distance >= 2) {
        currentLevel = 1;
      } else if (distance < 2) {
        currentLevel = 0;
      }
      if (!loadedModelLevels.get(modelName)?.has(currentLevel)) {
        loadModelLazy(modelName, currentLevel);
        loadedModelLevels.get(modelName)?.add(currentLevel);
      }
    }
  };

  loadModels();

  setTimeout(() => {
    console.log(lodObjects);
  }, 1000);

  return {
    lodObjects,
    onLodAnimate: useThrottleFn(onLodAnimate, 200),
  };
}
